package org.example.uhy.application.service.impl;

import org.example.uhy.application.context.ServiceContext;
import org.example.uhy.application.converter.MemberConverter;
import org.example.uhy.application.dto.MemberInfo;
import org.example.uhy.application.dto.MemberQueryCondition;
import org.example.uhy.application.dto.RegisterMemberDto;
import org.example.uhy.application.service.MemberService;
import org.example.uhy.domain.model.member.*;
import org.example.uhy.exceptions.EntityNotFoundException;
import org.example.uhy.supports.meta.ApplicationService;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 会员应用层服务实现类，提供粗粒度服务接口，并且处理事务
 * <p>
 * 领域模型中不建议使用{@link Autowire}，而应用层中可以使用，即与具体的某些技术结合
 */
@Service
@ApplicationService
public class MemberServiceImpl implements MemberService {
    @Autowired
    MemberRepository memberRepository;
    @Autowired
    MemberLevelRepository levelRepository;
    @Autowired
    MemberConverter memberConverter;

    @Override
    public List<MemberInfo> members(MemberQueryCondition condition, ServiceContext context) {
        boolean hasLabelCondition = !StringUtils.isEmpty(condition.getLabel());
        boolean hasLevelCondition = !StringUtils.isEmpty(condition.getLevel());
        if (hasLabelCondition && hasLevelCondition) {
            List<Member> members = memberRepository.members(MemberLabel.of(condition.getLabel()), MemberLevelId.of(condition.getLevel()));
            return convert(members);
        } else if (hasLabelCondition) {
            List<Member> members = memberRepository.membersOfLabel(MemberLabel.of(condition.getLabel()));
            return convert(members);
        } else if (hasLevelCondition) {
            List<Member> members = memberRepository.membersOfLevel(MemberLevelId.of(condition.getLevel()));
            return convert(members);
        } else {
            throw new IllegalArgumentException("请输入查询条件");
        }
    }

    @Override
    public MemberInfo memberOfId(String memberId, ServiceContext context) {
        Optional<Member> fetchedMember = memberRepository.memberOfId(MemberId.of(memberId));
        return fetchedMember.isPresent() ? memberConverter.convert(fetchedMember.get()) : null;
    }

    @Override
    public MemberId register(RegisterMemberDto memberDto, ServiceContext context) {
        // 获取默认级别
        MemberLevel defaultLevel = levelRepository.defaultMemberLevel();
        // 创建Member
        Member member = new Member(
                memberRepository.nextIdentity(),
                memberDto.getName(),
                defaultLevel.levelId(),
                Phone.of(memberDto.getPhone())
        );
        memberRepository.add(member);
        return member.memberId();
    }

    private List<MemberInfo> convert(List<Member> members) {
        return members.stream().map(member -> memberConverter.convert(member)).collect(Collectors.toList());
    }

    @Override
    public void calculateGrade(String memberId, ServiceContext context) {
        Optional<Member> fetchedMember = memberRepository.memberOfId(MemberId.of(memberId));
        if (!fetchedMember.isPresent()) {
            throw new EntityNotFoundException("会员不存在");
        }
        Member member = fetchedMember.get();
        member.calculateGrade();
        memberRepository.save(member);
    }

    @Override
    public void mark(String memberId, String label, ServiceContext context) {
        Optional<Member> fetchedMember = memberRepository.memberOfId(MemberId.of(memberId));
        if (!fetchedMember.isPresent()) {
            throw new EntityNotFoundException("会员不存在");
        }
        Member member = fetchedMember.get();
        member.mark(MemberLabel.of(label));
        memberRepository.save(member);
    }

    @Override
    public void unMark(String memberId, ServiceContext context) {
        Optional<Member> fetchedMember = memberRepository.memberOfId(MemberId.of(memberId));
        if (!fetchedMember.isPresent()) {
            throw new EntityNotFoundException("会员不存在");
        }
        Member member = fetchedMember.get();
        member.unMark();
        memberRepository.save(member);
    }
}
